﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace AMS.Chess.CommonLayer
{
    public class KingMove : AMove
    {
        public KingMove(AChessBoard board)
            : base(board)
        {

        }

        protected override List<ABoardPosition> GenerateMoves(AChessPiece movingPiece, ABoardPosition startPosition)
        {
            // valid position and valid piece/position match already verified with board

            StandardBoardPosition originalPosition = startPosition as StandardBoardPosition;
            if (originalPosition == null)
                throw new ArgumentException("Invalid position type");

            StandardChessBoard board = _board as StandardChessBoard;
            if (board == null)
                throw new ArgumentException("Invalid board");

            // generate all 8 possible moves
            List<ABoardPosition> possibleMoves = new List<ABoardPosition>();

            GenerateKingMoves(board, movingPiece, originalPosition, possibleMoves);

            return possibleMoves;
        }

        public static void GenerateKingMoves(StandardChessBoard board, AChessPiece movingPiece, StandardBoardPosition originalPosition, List<ABoardPosition> possibleMoves)
        {
            // TODO: Implement Castling

            // genearate all 8 possible moves
            List<ABoardPosition> generatedMoves = new List<ABoardPosition>();

            int i = originalPosition.Rank + 1;
            char j = (char)((int)originalPosition.File + 1);
            if (i <= StandardChessBoard.MaxRank && j <= StandardChessBoard.MaxFile)
                generatedMoves.Add(new StandardBoardPosition(i, j));

            i = originalPosition.Rank - 1;
            j = (char)((int)originalPosition.File + 1);
            if (i >= StandardChessBoard.MinRank && j <= StandardChessBoard.MaxFile)
                generatedMoves.Add(new StandardBoardPosition(i, j));

            i = originalPosition.Rank + 1;
            j = (char)((int)originalPosition.File - 1);
            if (i <= StandardChessBoard.MaxRank && j >= StandardChessBoard.MinFile)
                generatedMoves.Add(new StandardBoardPosition(i, j));

            i = originalPosition.Rank - 1;
            j = (char)((int)originalPosition.File - 1);
            if (i >= StandardChessBoard.MinRank && j >= StandardChessBoard.MinFile)
                generatedMoves.Add(new StandardBoardPosition(i, j));

            i = originalPosition.Rank + 1;
            j = (originalPosition.File);
            if (i <= StandardChessBoard.MaxRank)
                generatedMoves.Add(new StandardBoardPosition(i, j));

            i = originalPosition.Rank - 1;
            j = (originalPosition.File);
            if (i >= StandardChessBoard.MinRank)
                generatedMoves.Add(new StandardBoardPosition(i, j));

            i = originalPosition.Rank;
            j = (char)((int)originalPosition.File + 1);
            if (j <= StandardChessBoard.MaxFile)
                generatedMoves.Add(new StandardBoardPosition(i, j));

            i = originalPosition.Rank;
            j = (char)((int)originalPosition.File - 1);
            if (j >= StandardChessBoard.MinFile)
                generatedMoves.Add(new StandardBoardPosition(i, j));

            // add only valid moves to possibleMoves
            foreach (ABoardPosition p in generatedMoves)
            {
                TestSpace(movingPiece.Color, board, p as StandardBoardPosition, possibleMoves);
            }
        }

        /// <returns>A bool indicating if iteration loop should continue.</returns>
        private static bool TestSpace(ChessColor pieceColor, StandardChessBoard board, StandardBoardPosition targetPosition, List<ABoardPosition> possibleMoves)
        {
            AStandardChessPiece piece = board.GetPiece(targetPosition) as AStandardChessPiece;

            //empty?
            if (piece == null)
            {
                possibleMoves.Add(targetPosition);  // legit target space
                return true;    // check the next space
            }
            //enemy?
            else if (piece.Color != pieceColor)
            {
                possibleMoves.Add(targetPosition);  // legit target space
                return false;   // can't continue
            }
            else
            {
                // can't capture an ally
                return false;   // can't continue
            }
        }
    }
}
